#!/bin/bash
# Mole - Main Entry Point
# A comprehensive macOS maintenance tool
#
# Clean - Remove junk files and optimize system
# Uninstall - Remove applications completely
# Analyze - Interactive disk space explorer
#
# Usage:
#   ./mole                         # Interactive main menu
#   ./mole clean                   # Direct clean mode
#   ./mole uninstall               # Direct uninstall mode
#   ./mole analyze                 # Disk space explorer
#   ./mole --help                  # Show help

set -euo pipefail

# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Source common functions
source "$SCRIPT_DIR/lib/common.sh"

# Version info
VERSION="1.10.0"
MOLE_TAGLINE="can dig deep to clean your Mac."

# Get latest version from remote repository
get_latest_version() {
    curl -fsSL --connect-timeout 2 --max-time 3 -H "Cache-Control: no-cache" \
        "https://raw.githubusercontent.com/tw93/mole/main/mole" 2> /dev/null |
        grep '^VERSION=' | head -1 | sed 's/VERSION="\(.*\)"/\1/'
}

# Get latest version from Homebrew for brew-installed Mole
get_latest_brew_version() {
    if ! command -v brew > /dev/null 2>&1; then
        return 1
    fi

    brew info --json=v2 mole 2> /dev/null | grep -o '"version":"[^"]*"' | head -1 | sed 's/"version":"\(.*\)"/\1/'
}

# Check if installed via Homebrew
is_homebrew_install() {
    command -v brew > /dev/null 2>&1 && brew list mole > /dev/null 2>&1
}

# Check for updates (non-blocking, cached)
check_for_updates() {
    local cache="$HOME/.cache/mole/version_check"
    local msg_cache="$HOME/.cache/mole/update_message"
    local debug_log="$HOME/.cache/mole/update_check_debug"
    local ttl="${MO_UPDATE_CHECK_TTL:-3600}"
    mkdir -p "$(dirname "$cache")" 2> /dev/null

    # Skip if checked recently
    if [[ -f "$cache" ]]; then
        local age=$(($(date +%s) - $(stat -f%m "$cache" 2> /dev/null || echo 0)))
        [[ $age -lt $ttl ]] && return
    fi

    # Background version check (save to file, don't output)
    (
        local latest
        local check_method=""

        # For Homebrew installations, check Homebrew version
        if is_homebrew_install; then
            latest=$(get_latest_brew_version)
            check_method="brew"
            [[ -n "${MO_UPDATE_DEBUG:-}" ]] && echo "$(date): Checking via Homebrew, got: $latest" >> "$debug_log"
        fi

        # Fallback to GitHub for non-brew or if brew check failed
        if [[ -z "$latest" ]]; then
            latest=$(get_latest_version)
            check_method="github"
            [[ -n "${MO_UPDATE_DEBUG:-}" ]] && echo "$(date): Checking via GitHub, got: $latest" >> "$debug_log"
        fi

        if [[ -n "$latest" && "$VERSION" != "$latest" && "$(printf '%s\n' "$VERSION" "$latest" | sort -V | head -1)" == "$VERSION" ]]; then
            printf "\nUpdate available: %s → %s, run %smo update%s\n\n" "$VERSION" "$latest" "$GREEN" "$NC" > "$msg_cache"
            [[ -n "${MO_UPDATE_DEBUG:-}" ]] && echo "$(date): Update available ($check_method): $VERSION → $latest" >> "$debug_log"
        else
            echo -n > "$msg_cache"
            [[ -n "${MO_UPDATE_DEBUG:-}" ]] && echo "$(date): No update needed ($check_method): $VERSION == $latest" >> "$debug_log"
        fi
        touch "$cache" 2> /dev/null
    ) &
    disown 2> /dev/null || true
}

# Show update notification if available
show_update_notification() {
    local msg_cache="$HOME/.cache/mole/update_message"
    if [[ -f "$msg_cache" && -s "$msg_cache" ]]; then
        cat "$msg_cache"
        echo
    fi
}

show_brand_banner() {
    cat << EOF
${GREEN} __  __       _      ${NC}
${GREEN}|  \/  | ___ | | ___ ${NC}
${GREEN}| |\/| |/ _ \| |/ _ \\${NC}
${GREEN}| |  | | (_) | |  __/${NC}  ${BLUE}https://github.com/tw93/mole${NC}
${GREEN}|_|  |_|\___/|_|\___|${NC}  ${GREEN}${MOLE_TAGLINE}${NC}

EOF
}

animate_mole_intro() {
    # Skip animation if stdout isn't a TTY (non-interactive)
    if [[ ! -t 1 ]]; then
        return
    fi

    clear_screen
    printf '\n'
    hide_cursor

    local -a mole_lines=()
    while IFS= read -r line; do
        mole_lines+=("$line")
    done << 'EOF'
        /\_/\
   ____/ o o \
 /~____  =o= /
(______)__m_m)
        /   \
     __/ /\ \__
    /__/  \__\_
EOF

    local idx
    local body_cutoff=4
    local body_color="${PURPLE}"
    local ground_color="${GREEN}"
    for idx in "${!mole_lines[@]}"; do
        if ((idx < body_cutoff)); then
            printf "%s\n" "${body_color}${mole_lines[$idx]}${NC}"
        else
            printf "%s\n" "${ground_color}${mole_lines[$idx]}${NC}"
        fi
        sleep 0.1
    done

    printf '\n'
    sleep 0.5

    printf '\033[2J\033[H'
    show_cursor
}

show_version() {
    printf '\nMole version %s\n\n' "$VERSION"
}

show_help() {
    show_brand_banner
    echo
    printf "%s%s%s\n" "$BLUE" "COMMANDS" "$NC"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo" "$NC" "Interactive main menu"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo clean" "$NC" "Deeper system cleanup"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo clean --dry-run" "$NC" "Preview cleanup (no deletions)"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo clean --whitelist" "$NC" "Manage protected caches"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo uninstall" "$NC" "Remove applications completely"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo optimize" "$NC" "System health check & optimization"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo analyze" "$NC" "Interactive disk space explorer"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo status" "$NC" "System status dashboard"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo touchid" "$NC" "Configure Touch ID for sudo"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo update" "$NC" "Update Mole to the latest version"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo remove" "$NC" "Remove Mole from the system"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo --version" "$NC" "Show installed version"
    printf "  %s%-28s%s %s\n" "$GREEN" "mo --help" "$NC" "Show this help message"

    printf "\n%s%s%s\n" "$BLUE" "MORE" "$NC"
    printf "  https://github.com/tw93/mole\n\n"
}

# Simple update function
update_mole() {
    # Check if installed via Homebrew
    if is_homebrew_install; then
        update_via_homebrew "$VERSION"
        exit 0
    fi

    # Check for updates
    local latest
    latest=$(get_latest_version)

    if [[ -z "$latest" ]]; then
        log_error "Unable to check for updates. Check network connection."
        exit 1
    fi

    if [[ "$VERSION" == "$latest" ]]; then
        echo ""
        echo -e "${GREEN}${ICON_SUCCESS}${NC} Already on latest version (${VERSION})"
        echo ""
        exit 0
    fi

    # Download and run installer with progress
    if [[ -t 1 ]]; then
        start_inline_spinner "Downloading latest version..."
    else
        echo "Downloading latest version..."
    fi

    local installer_url="https://raw.githubusercontent.com/tw93/mole/main/install.sh"
    local tmp_installer
    tmp_installer="$(mktemp_file)" || {
        log_error "Update failed"
        exit 1
    }

    # Download installer with progress
    if command -v curl > /dev/null 2>&1; then
        if ! curl -fsSL --connect-timeout 10 --max-time 60 "$installer_url" -o "$tmp_installer" 2>&1; then
            if [[ -t 1 ]]; then stop_inline_spinner; fi
            rm -f "$tmp_installer"
            log_error "Update failed. Check network connection."
            exit 1
        fi
    elif command -v wget > /dev/null 2>&1; then
        if ! wget --timeout=10 --tries=3 -qO "$tmp_installer" "$installer_url" 2>&1; then
            if [[ -t 1 ]]; then stop_inline_spinner; fi
            rm -f "$tmp_installer"
            log_error "Update failed. Check network connection."
            exit 1
        fi
    else
        if [[ -t 1 ]]; then stop_inline_spinner; fi
        rm -f "$tmp_installer"
        log_error "curl or wget required"
        exit 1
    fi

    if [[ -t 1 ]]; then stop_inline_spinner; fi
    chmod +x "$tmp_installer"

    # Determine install directory
    local mole_path
    mole_path="$(command -v mole 2> /dev/null || echo "$0")"
    local install_dir
    install_dir="$(cd "$(dirname "$mole_path")" && pwd)"

    if [[ -t 1 ]]; then
        start_inline_spinner "Installing update..."
    else
        echo "Installing update..."
    fi

    # Helper function to process installer output
    process_install_output() {
        local output="$1"
        if [[ -t 1 ]]; then stop_inline_spinner; fi

        local filtered_output
        filtered_output=$(printf '%s\n' "$output" | sed '/^$/d')
        if [[ -n "$filtered_output" ]]; then
            printf '\n%s\n' "$filtered_output"
        fi

        # Only show success message if installer didn't already do so
        if ! printf '%s\n' "$output" | grep -Eq "Updated to latest version|Already on latest version"; then
            local new_version
            new_version=$("$mole_path" --version 2> /dev/null | awk 'NF {print $NF}' || echo "")
            printf '\n%s\n\n' "${GREEN}${ICON_SUCCESS}${NC} Updated to latest version (${new_version:-unknown})"
        else
            printf '\n'
        fi
    }

    # Run installer with visible output (but capture for error handling)
    local install_output
    if install_output=$("$tmp_installer" --prefix "$install_dir" --config "$HOME/.config/mole" --update 2>&1); then
        process_install_output "$install_output"
    else
        # Retry without --update flag
        if install_output=$("$tmp_installer" --prefix "$install_dir" --config "$HOME/.config/mole" 2>&1); then
            process_install_output "$install_output"
        else
            if [[ -t 1 ]]; then stop_inline_spinner; fi
            rm -f "$tmp_installer"
            log_error "Update failed"
            echo "$install_output" | tail -10 >&2 # Show last 10 lines of error
            exit 1
        fi
    fi

    rm -f "$tmp_installer"
    rm -f "$HOME/.cache/mole/version_check" "$HOME/.cache/mole/update_message"
}

# Remove Mole from system
remove_mole() {
    # Detect all installations with loading
    if [[ -t 1 ]]; then
        start_inline_spinner "Detecting Mole installations..."
    else
        echo "Detecting installations..."
    fi

    local is_homebrew=false
    local -a manual_installs=()
    local -a alias_installs=()

    # Check Homebrew
    if is_homebrew_install; then
        is_homebrew=true
    fi

    # Find mole installations using which/command
    local found_mole
    found_mole=$(command -v mole 2> /dev/null || true)
    if [[ -n "$found_mole" && -f "$found_mole" ]]; then
        # Check if it's not a Homebrew symlink
        if [[ ! -L "$found_mole" ]] || ! readlink "$found_mole" | grep -q "Cellar/mole"; then
            manual_installs+=("$found_mole")
        fi
    fi

    # Also check common locations as fallback
    local -a fallback_paths=(
        "/usr/local/bin/mole"
        "$HOME/.local/bin/mole"
        "/opt/local/bin/mole"
    )

    for path in "${fallback_paths[@]}"; do
        if [[ -f "$path" && "$path" != "$found_mole" ]]; then
            # Check if it's not a Homebrew symlink
            if [[ ! -L "$path" ]] || ! readlink "$path" | grep -q "Cellar/mole"; then
                manual_installs+=("$path")
            fi
        fi
    done

    # Find mo alias
    local found_mo
    found_mo=$(command -v mo 2> /dev/null || true)
    if [[ -n "$found_mo" && -f "$found_mo" ]]; then
        alias_installs+=("$found_mo")
    fi

    # Also check common locations for mo
    local -a alias_fallback=(
        "/usr/local/bin/mo"
        "$HOME/.local/bin/mo"
        "/opt/local/bin/mo"
    )

    for alias in "${alias_fallback[@]}"; do
        if [[ -f "$alias" && "$alias" != "$found_mo" ]]; then
            alias_installs+=("$alias")
        fi
    done

    if [[ -t 1 ]]; then
        stop_inline_spinner
    fi

    printf '\n'

    # Check if anything to remove
    local manual_count=${#manual_installs[@]}
    local alias_count=${#alias_installs[@]}
    if [[ "$is_homebrew" == "false" && ${manual_count:-0} -eq 0 && ${alias_count:-0} -eq 0 ]]; then
        printf '%s\n\n' "${YELLOW}No Mole installation detected${NC}"
        exit 0
    fi

    # Show what will be removed
    echo -e "${YELLOW}Remove Mole${NC} - will delete the following:"
    if [[ "$is_homebrew" == "true" ]]; then
        echo "  - Mole via Homebrew"
    fi
    for install in ${manual_installs[@]+"${manual_installs[@]}"} ${alias_installs[@]+"${alias_installs[@]}"}; do
        echo "  - $install"
    done
    echo "  - ~/.config/mole"
    echo "  - ~/.cache/mole"
    echo -ne "${PURPLE}${ICON_ARROW}${NC} Press ${GREEN}Enter${NC} to confirm, ${GRAY}ESC${NC} to cancel: "

    # Read single key
    IFS= read -r -s -n1 key || key=""
    drain_pending_input # Clean up any escape sequence remnants
    case "$key" in
        $'\e')
            echo -e "${GRAY}Cancelled${NC}"
            echo ""
            exit 0
            ;;
        "" | $'\n' | $'\r')
            printf "\r\033[K" # Clear the prompt line
            # Continue with removal
            ;;
        *)
            echo -e "${GRAY}Cancelled${NC}"
            echo ""
            exit 0
            ;;
    esac

    # Remove Homebrew installation (silent)
    local has_error=false
    if [[ "$is_homebrew" == "true" ]]; then
        if ! brew uninstall mole > /dev/null 2>&1; then
            has_error=true
        fi
    fi
    # Remove manual installations
    if [[ ${manual_count:-0} -gt 0 ]]; then
        for install in "${manual_installs[@]}"; do
            if [[ -f "$install" ]]; then
                # Check if directory requires sudo (deletion is a directory operation)
                if [[ ! -w "$(dirname "$install")" ]]; then
                    # Requires sudo
                    if ! sudo rm -f "$install" 2> /dev/null; then
                        has_error=true
                    fi
                else
                    # Regular user permission
                    if ! rm -f "$install" 2> /dev/null; then
                        has_error=true
                    fi
                fi
            fi
        done
    fi
    if [[ ${alias_count:-0} -gt 0 ]]; then
        for alias in "${alias_installs[@]}"; do
            if [[ -f "$alias" ]]; then
                # Check if directory requires sudo
                if [[ ! -w "$(dirname "$alias")" ]]; then
                    sudo rm -f "$alias" 2> /dev/null || true
                else
                    rm -f "$alias" 2> /dev/null || true
                fi
            fi
        done
    fi
    # Clean up cache first (silent)
    if [[ -d "$HOME/.cache/mole" ]]; then
        rm -rf "$HOME/.cache/mole" 2> /dev/null || true
    fi
    # Clean up configuration last (silent)
    if [[ -d "$HOME/.config/mole" ]]; then
        rm -rf "$HOME/.config/mole" 2> /dev/null || true
    fi

    # Show final result
    local final_message
    if [[ "$has_error" == "true" ]]; then
        final_message="${YELLOW}${ICON_ERROR} Mole uninstalled with some errors, thank you for using Mole!${NC}"
    else
        final_message="${GREEN}${ICON_SUCCESS} Mole uninstalled successfully, thank you for using Mole!${NC}"
    fi
    printf '\n%s\n\n' "$final_message"

    exit 0
}

# Display main menu options with minimal refresh to avoid flicker
show_main_menu() {
    local selected="${1:-1}"
    local _full_draw="${2:-true}" # Kept for compatibility (unused)
    local banner="${MAIN_MENU_BANNER:-}"
    local update_message="${MAIN_MENU_UPDATE_MESSAGE:-}"

    # Fallback if globals missing (should not happen)
    if [[ -z "$banner" ]]; then
        banner="$(show_brand_banner)"
        MAIN_MENU_BANNER="$banner"
    fi

    printf '\033[H' # Move cursor to home

    local line=""
    # Leading spacer
    printf '\r\033[2K\n'

    # Brand banner
    while IFS= read -r line || [[ -n "$line" ]]; do
        printf '\r\033[2K%s\n' "$line"
    done <<< "$banner"

    # Update notification block (if present)
    if [[ -n "$update_message" ]]; then
        while IFS= read -r line || [[ -n "$line" ]]; do
            printf '\r\033[2K%s\n' "$line"
        done <<< "$update_message"
    fi

    # Spacer before menu options
    printf '\r\033[2K\n'

    printf '\r\033[2K%s\n' "$(show_menu_option 1 "Clean Mac - Remove junk files and optimize" "$([[ $selected -eq 1 ]] && echo true || echo false)")"
    printf '\r\033[2K%s\n' "$(show_menu_option 2 "Uninstall Apps - Remove applications completely" "$([[ $selected -eq 2 ]] && echo true || echo false)")"
    printf '\r\033[2K%s\n' "$(show_menu_option 3 "Optimize Mac - System health & tuning" "$([[ $selected -eq 3 ]] && echo true || echo false)")"
    printf '\r\033[2K%s\n' "$(show_menu_option 4 "Analyze Disk - Interactive space explorer" "$([[ $selected -eq 4 ]] && echo true || echo false)")"
    printf '\r\033[2K%s\n' "$(show_menu_option 5 "System Status - Live CPU/GPU/memory" "$([[ $selected -eq 5 ]] && echo true || echo false)")"

    if [[ -t 0 ]]; then
        printf '\r\033[2K\n'
        printf '\r\033[2K%s\n' "${GRAY}↑↓  |  Enter  |  H Help  |  V Version  |  Q Quit${NC}"
        printf '\r\033[2K\n'
    fi

    # Clear any remaining content below without full screen wipe
    printf '\033[J'
}

# Interactive main menu loop
interactive_main_menu() {
    # Show intro animation only once per terminal tab
    if [[ -t 1 ]]; then
        local tty_name
        tty_name=$(tty 2> /dev/null || echo "")
        if [[ -n "$tty_name" ]]; then
            local flag_file
            local cache_dir="$HOME/.cache/mole"
            mkdir -p "$cache_dir" 2> /dev/null
            flag_file="$cache_dir/intro_$(echo "$tty_name" | tr -c '[:alnum:]_' '_')"
            if [[ ! -f "$flag_file" ]]; then
                animate_mole_intro
                touch "$flag_file" 2> /dev/null || true
            fi
        fi
    fi
    local current_option=1
    local first_draw=true
    local brand_banner=""
    local msg_cache="$HOME/.cache/mole/update_message"
    local update_message=""

    brand_banner="$(show_brand_banner)"
    MAIN_MENU_BANNER="$brand_banner"

    if [[ -f "$msg_cache" && -s "$msg_cache" ]]; then
        update_message="$(cat "$msg_cache" 2> /dev/null || echo "")"
    fi
    MAIN_MENU_UPDATE_MESSAGE="$update_message"

    cleanup_and_exit() {
        show_cursor
        exit 0
    }

    trap cleanup_and_exit INT
    hide_cursor

    while true; do
        show_main_menu $current_option "$first_draw"
        if [[ "$first_draw" == "true" ]]; then
            first_draw=false
        fi

        local key
        if ! key=$(read_key); then
            continue
        fi

        case "$key" in
            "UP") ((current_option > 1)) && ((current_option--)) ;;
            "DOWN") ((current_option < 5)) && ((current_option++)) ;;
            "ENTER")
                show_cursor
                case $current_option in
                    1) exec "$SCRIPT_DIR/bin/clean.sh" ;;
                    2) exec "$SCRIPT_DIR/bin/uninstall.sh" ;;
                    3) exec "$SCRIPT_DIR/bin/optimize.sh" ;;
                    4) exec "$SCRIPT_DIR/bin/analyze.sh" ;;
                    5) exec "$SCRIPT_DIR/bin/status.sh" ;;
                esac
                ;;
            "CHAR:1")
                show_cursor
                exec "$SCRIPT_DIR/bin/clean.sh"
                ;;
            "CHAR:2")
                show_cursor
                exec "$SCRIPT_DIR/bin/uninstall.sh"
                ;;
            "CHAR:3")
                show_cursor
                exec "$SCRIPT_DIR/bin/optimize.sh"
                ;;
            "CHAR:4")
                show_cursor
                exec "$SCRIPT_DIR/bin/analyze.sh"
                ;;
            "CHAR:5")
                show_cursor
                exec "$SCRIPT_DIR/bin/status.sh"
                ;;
            "HELP")
                show_cursor
                clear
                show_help
                exit 0
                ;;
            "VERSION")
                show_cursor
                clear
                show_version
                exit 0
                ;;
            "QUIT") cleanup_and_exit ;;
        esac

        # Drain any accumulated input after processing (e.g., touchpad scroll events)
        drain_pending_input
    done
}

main() {
    case "${1:-""}" in
        "optimize")
            exec "$SCRIPT_DIR/bin/optimize.sh"
            ;;
        "clean")
            exec "$SCRIPT_DIR/bin/clean.sh" "${@:2}"
            ;;
        "uninstall")
            exec "$SCRIPT_DIR/bin/uninstall.sh"
            ;;
        "analyze")
            exec "$SCRIPT_DIR/bin/analyze.sh" "${@:2}"
            ;;
        "status")
            exec "$SCRIPT_DIR/bin/status.sh" "${@:2}"
            ;;
        "touchid")
            exec "$SCRIPT_DIR/bin/touchid.sh" "${@:2}"
            ;;
        "update")
            update_mole
            exit 0
            ;;
        "remove")
            remove_mole
            exit 0
            ;;
        "help" | "--help" | "-h")
            show_help
            exit 0
            ;;
        "version" | "--version" | "-V")
            show_version
            exit 0
            ;;
        "")
            check_for_updates
            interactive_main_menu
            ;;
        *)
            echo "Unknown command: $1"
            echo "Use 'mole --help' for usage information."
            exit 1
            ;;
    esac
}

main "$@"
